<?php

namespace Jinxing\Admin\Http\Middleware;

use Closure;
use Illuminate\View\View;
use Illuminate\Http\JsonResponse;
use Jinxing\Admin\Traits\ExceptTrait;
use Illuminate\Pagination\LengthAwarePaginator;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * Class Json 处理响应json 数据
 * @package Jinxing\Admin\Http\Middleware
 */
class Json
{
    use ExceptTrait;

    /**
     * 需要排除的地址
     *
     * @var array
     */
    protected $except = [
        'index/index',
    ];

    /**
     * @var array json 格式必须需要的字段
     */
    protected $jsonFormatAttributes = ['code', 'msg', 'data'];

    /**
     * @var array 成功的json
     */
    protected $successJson = [
        'code' => 0,
        'msg'  => 'success',
        'data' => [],
    ];

    /**
     * @var array 错误返回的json
     */
    protected $errorJson = [
        'code' => 500,
        'msg'  => 'fail',
        'data' => [],
    ];


    /**
     * 处理成功返回自定义格式
     *
     * @param \Illuminate\Http\Request $request
     * @param Closure                  $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        // 如果是导出Excel类型直接返回、file 文件类型、或者需要排除的路径、直接返回
        if ($response instanceof BinaryFileResponse || $this->inExceptArray($request, $this->except)) {
            return $response;
        }

        // 响应数据
        $data = $response->getOriginalContent();

        // 视图响应不处理
        if ($data instanceof View) {
            return $response;
        }

        // 本来就是json数据返回、需要判断是否为我们需要的json格式
        if ($response instanceof JsonResponse) {

            // 使用的是json 的返回数据
            if ($this->isJsonFormat($data)) {
                return $response;
            }

            // 分页数据处理
            if ($data instanceof LengthAwarePaginator) {
                $data = $this->formatPaginate($data);
            }

            $response->setData(array_merge($this->successJson, ['data' => $data]));
            return $response;
        }

        // 存在错误信息
        if ($response->exception instanceof \Exception) {
            return response()->json(array_merge($this->errorJson, [
                'msg' => app()->isLocal() ? $response->exception->getMessage() : '程序运行出现错误、请稍后再试',
            ]));
        }

        return response()->json(array_merge($this->successJson, ['data' => $data]));
    }

    /**
     * 格式化分页数据信息
     *
     * @param LengthAwarePaginator $paginate 分页对象
     *
     * @return array
     */
    protected function formatPaginate($paginate)
    {
        return [
            'items'    => $paginate->items(),
            'paginate' => [
                'current' => $paginate->currentPage(),
                'size'    => $paginate->perPage(),
                'total'   => $paginate->total(),
            ],
        ];
    }

    /**
     * 判断数据是否为需要的json 格式
     *
     * @param array|mixed $data 数据信息
     *
     * @return bool
     */
    protected function isJsonFormat($data)
    {
        // 必须要是数组
        if (is_array($data)) {
            $number = 0;
            foreach ($this->jsonFormatAttributes as $attribute) {
                if (isset($data[$attribute])) {
                    $number++;
                }
            }

            return count($this->jsonFormatAttributes) === $number;
        }

        return false;
    }
}
